﻿/// <reference path="jquery-1.4.2.js" />

$(function () {

    var alertEle;
    // 提交数组格式设置
    $.ajaxSettings.traditional = true;
    $.ajaxSettings.cache = false;
    $('#exportSearch').click(
			function () {
			    var self = $(this);
			    var url = this.href
						+ '?'
						+ $.param(self.parents('.TableRegion').find(':input')
								.SerializeElements());
			    window.open(url);
			    return false;
			});
    $.handleError = function (s, xhr, status, e) {
        // If a local callback was specified, fire it
        if (s.error) {
            s.error.call(s.context || s, xhr, status, e);
        }

        // Fire the global callback
        if (s.global) {
            (s.context ? jQuery(s.context) : jQuery.event).trigger("ajaxError",
					[xhr, s, e]);
        }
    };
    // $("a.export").click(function() {

    // var self = $(this);
    // var url = this.href + '?' +
    // $.param(self.parents('.TableRegion').find(':input').SerializeElements());
    // window.open(url);
    // return false;
    //   
    // });

    $(':input').focus(function () {
        $(this).addClass('focus');
    }).blur(function () {
        $(this).removeClass('focus');
    });
    $('dl.dlf,dl.dlf>dt,dl.dlf>dd').each(function () {
        $(this).addClass('inlineBlock inline');
    });
    $('ul.ul-datalist>li>dl>dt,ul.ul-datalist>li>dl>dd').each(function () {
        $(this).addClass('inlineBlock inline');
    });

    $('input:submit:not(:has(".login"))').addClass('normal');

    // 时间设置
    /*
    * $.datepicker.setDefaults({ autoSize: true, dateFormat: "yyyy-MM-dd",
    * changeMonth: true, changeYear: true, yearRange: 'c-100:c+10' });
    * $.datepicker.setDefaults($.datepicker.regional['zh-CN']);
    * $.fn.getContraryDate = function() { var isMin = false; var targetInput;
    * var limitName = $(this).attr("name"); if (limitName) { var i =
    * limitName.lastIndexOf('.Start'); if (i > 0) { isMin = true; limitName =
    * limitName.substr(0, i); targetInput = $('input:[name="' + limitName +
    * '.End' + '"]'); } else { i = limitName.lastIndexOf('.End'); isMin =
    * false; limitName = limitName.substr(0, i); targetInput =
    * $('input:[name="' + limitName + '.Start' + '"]'); } } if (!limitName) {
    * limitName = $(this).attr('maxdate'); if (limitName) { isMin = false;
    * targetInput = $('input:[mindate="' + limitName + '"]'); } else {
    * limitName = $(this).attr('mindate'); if (limitName) { isMin = true;
    * targetInput = $('input:[maxdate="' + limitName + '"]'); } } } return {
    * isMin: isMin, targetInput: targetInput }; }; // var limitDate =
    * function(selectedDate, isdatetime) { //// var options =
    * $(this).getContraryDate(); //// var isMin = options.isMin; //// var
    * targetInput = options.targetInput;
    * 
    * //// if (targetInput.length == 0) return; //// var date =
    * $(this).datepicker("getDate"); //// if (!isdatetime) ////
    * targetInput.datepicker("option", isMin ? "minDate" : "maxDate", date);
    * //// else //// targetInput.datetimepicker("option", isMin ? "minDate" :
    * "maxDate", date); // };
    */
    $('input[tag="date"]').datepicker({
        dateFormat: "yy-mm-dd"
    }).attr('readonly', true);
    // $('input[tag="datetime"]').attr('style', 'width:150px;').datetimepicker({
    // clockType: 24
    // // , onSelect: function(selecteddate) {
    // // limitDate.apply(this, [selecteddate, true]);
    // // }
    //
    // }).attr('readonly', true);

    // 反序列化字符串
    $.StringToJson = function (str) {
        var qsobj = {};
        var thisqs = str.split('?')[1];

        if (thisqs) {
            var pairs = thisqs.split('&');
            for (var i = 0; i < pairs.length; i++) {
                var pair = pairs[i].split('=');
                qsobj[pair[0]] = pair[1];
            }
        }
        return qsobj;
    };

    // a Button 效果
    $('a.Button').each(
			function () {
			    var css = $(this).removeClass('Button').attr('class');
			    $(this).addClass('Button');
			    var content = $(this).html();
			    $(this).empty().append('<span class="icon ' + css + '"/>')
						.append($('<span class="content"/>').html(content));
			});

    $('div.topOperRegion>a.tb-btn:odd').each(function () {
        $('<span class="tb-btn-split"></span>').insertBefore(this);
    });

    // 调试Log
    $.TraceEnabled = $.IsDebug = $('#_divDebug').length > 0;
    $.Trace = function (str) {
        $('#_divDebug').append(str + "<br />");
    };

    // 取消超链接的虚线框
    $("a").focus(function () {
        this.blur();
    });

    // form输入验证
    $('form').submit(function () {
        return $(this).validate();
    });

    // Ajax情况下的Form验证
    $.extend($, {
        ajaxSubmit: {
            options: {
                beforeSubmit: function (arr, $form, options) {
                    if (!$form.validate())
                        return false;
                    var dlg = $form.parents('.ui-dialog');
                    if (dlg.length > 0) {
                        var buttons = $('.ui-button', dlg);
                        buttons.attr('disabled', 'disabled');
                        var oldsuccess = options.success;
                        options.success = function () {
                            oldsuccess.apply($form, arguments);
                            buttons.removeAttr('disabled');
                        };

                    }
                    return true;
                }
            }
        }
    });

    // 全选复选框
    $(document).on(
			'click',
			'.datalist>thead>tr>td:first>:checkbox',
			function () {
			    var checked = $(this).attr('checked');
			    if (checked) {
			        $('.datalist>tbody>tr>td:first-child>:checkbox').attr(
							'checked', true);
			    } else {
			        $('.datalist>tbody>tr>td:first-child>:checkbox')
							.removeAttr('checked');
			    }
			});

    // ========================查询分页=================================//
    // 排序
    $(document).on('click', '.datalist thead td[sort]', function () {
        var self = $(this);

        var oDataTable = $(this).parents('.datalist').parent();
        var strId = oDataTable.attr('id');
        var oAction = $('#' + strId.substr(0, strId.length - 4));
        // 排序的字段
        var dataColumn = $(this).attr('sort');
        if (!dataColumn)
            return false;

        var query = oAction.data('query');

        // 获取上一次排序的值
        var oldColumn = "";
        var bIsasc = true;
        if (query.OrderBy) {
            var arr = query.OrderBy.split(" ");
            oldColumn = arr[0];
            bIsasc = arr[1] == 'asc';
        }

        if (oldColumn == dataColumn)
            bIsasc = !bIsasc;
        var strOrder = (bIsasc ? "asc" : "desc");
        query.OrderBy = dataColumn + " " + strOrder;
        query.PageIndex = 1;
        oAction.data('query', query);
        window.loadpage(oAction);

    });
    // 重新加载当前页
    $.fn.reloadPage = function () {
        window.loadpage(this);
    };
    // 查询并转到第一页
    $.fn.search = function () {
        $(this).click();
    };

    var pageSummary = function () {

        if ($(".datalist").hasClass("totalSummary") == false) {
            return;
        }

        var recCnt = $(".datalist").attr("recordcount");
        if (recCnt == null) {
            return;
        }

        var tableEle = $("div.topOperRegion>table");
        var ele;
        if (tableEle.length < 1) {
            ele = $("div.topOperRegion>span.summary");
            if (ele.length < 1) {
                ele = $("<span class='summary'></span>");
                $("div.topOperRegion").append(ele);
            }

        } else {
            ele = $("div.topOperRegion>table>tbody>tr>td.summary");
            if (ele.length < 1) {
                ele = $("<td class='summary'></td>");
                $("div.topOperRegion>table>tbody>tr").append(ele);
            }

        }

        ele.html('共：' + recCnt + '条记录');

    };
    // 回到顶部
    function BackTop() {
        $('html, body').animate({
            scrollTop: 0
        }, 500);
    }
    ;

    pageSummary();

    $.fn.SerializeElements = function (skipempty) {
        var items = {};
        this.each(function () {
            var fieldname = $(this).attr('datafield') || this.name;
            if (fieldname) {
                var self = $(this);
                if (self.is(':checkbox') || self.is(':radio')) {
                    if (self.attr('checked'))
                        items[fieldname] = $(this).val();
                } else {
                    var val = self.val();
                    if (!self.is(':input')) {
                        val = val || $.trim(self.text());
                    }
                    if (val == null || (val.length == 0 && skipempty))
                        return;
                    items[fieldname] = val;
                }
            }
        });
        return items;
    };

    $.fn.prepareQuery = function () {
        var self = $(this);
        var items = $(':input', self.parent().parent()).SerializeElements();
        var dateCtls = $('input[tag="date"][name$=".End"]', self.parent());
        dateCtls.each(function () {
            if ($.trim($(this).val()) != '') {
                var date = $(this).datepicker("getDate");
                date.setDate(date.getDate() + 1);
                var str = $.datepicker.formatDate(
						$.datepicker._defaults.dateFormat, date);
                items[this.name] = str;
            }
        });

        var query = $.extend({}, self.data("query"), items, {
            pageIndex: 1
        });
        self.data('query', query);
        return query;
    };

    $('a.searchbtn')
			.each(
					function () {
					    var self = $(this);
					    var oDataTable = $('#' + this.id + "Data");
					    var oPage = $('#' + this.id + "Page");
					    var query = {};
					    query.pageIndex = 1;
					    query.pageSize = self.attr("pagesize");
					    self.data('query', query);
					    query = self.prepareQuery();
					    // 创建加载页面的方法
					    if (!window.loadpage) {
					        window.loadpage = function (ele) {
					            var self = $(ele);
					            if (self.length == 0)
					                return;
					            var oDataTable = $('#' + self.attr('id')
										+ "Data");
					            var oPage = $('#' + self.attr('id') + "Page");
					            var query = self.data('query');
					            oDataTable
										.load(
												self.attr('href'),
												query,
												function () {
												    var data = oDataTable
															.children();
												    oPage
															.pages(
																	'changepage',
																	data
																			.attr("pageindex"),
																	data
																			.attr("recordcount"));

												    pageSummary();

												    // 显示排序信息
												    if (query.OrderBy) {
												        var arr = query.OrderBy
																.split(" ");
												        var oldColumn = arr[0];
												        var strOrder = ((arr[1] == 'asc') ? 'asc'
																: 'desc');
												        $(
																'thead td[sort="'
																		+ oldColumn
																		+ '"]',
																data)
																.addClass(
																		strOrder)
																.append(
																		'<img src="/Content/Images/'
																				+ strOrder
																				+ '.png"/>');
												    }
												    self.trigger('ajaxload');
												    stripe();
												    BackTop();
												});
					        };
					    }

					    oDataTable.load(self.attr('href'), query, function () {
					        var pagedata = oDataTable.children();
					        oPage.pages({
					            pageindex: pagedata.attr("pageindex"),
					            total: pagedata.attr("recordcount"),
					            max: 10,
					            pagesize: query.pageSize,
					            onpage: function (ui) {
					                var query = self.data('query');
					                query.pageIndex = ui.index;
					                self.data('query', query);
					                window.loadpage(self);
					            }
					        });

					    });

					});

    // 查询搜索
    $('a.searchbtn').click(function () {
        $(this).prepareQuery();
        window.loadpage(this);
        return false;
    });

    // ========================查询分页结束=================================//

    // 点击隐藏
    $(':checkbox.checkhide').bind('click change', function () {
        var checked = $(this).attr('checked');
        if ($(this).hasClass('reverse'))
            checked = !checked;
        if (checked)
            $('*[forid="' + this.id + '"]').show();
        else
            $('*[forid="' + this.id + '"]').hide();
    });

    $(':checkbox.checkhide').each(function () {
        $(this).triggerHandler('click');
    });

    // 弹出层显示ajax信息
    var popmove = function () {
        var self = $(this);
        self.die('mousemove', popmove);
        var aid = self.attr('id');
        var pop = $('#' + aid + 'Pop');
        var loadEle;
        if (pop.hasClass('loadcontent')) {
            loadEle = pop;
        } else {
            loadEle = $('.loadcontent', pop);
        }
        if (loadEle.attr('onloading')) {
            return false;
        } else {
            loadEle.waiting().attr('onloading', true).load(this.href,
					function () {
					    loadEle.removeAttr('onloading');
					});
        }
        pop.offset(self.offset()).css('zIndex', self.zIndex() + 1).show();
        pop.one('mouseleave', function () {
            $(this).hide();
        });
        return false;
    };
    $(document).on('mousemove', 'a.popshow', popmove);

    $.ActionResponse = function (icontype, title, content, callback,
			cancelcallback) {
        if (!alertEle) {
            // alertEle = $('<div id="ico"><div
            // id="content"></div></div>').appendTo($(document.body));
            alertEle = $('<div id="ico"><div id="img"></div></div>').appendTo(
					$(document.body));
        }
        if (title == '')
            title = '提示';
        $('p', alertEle).remove();
        $('<p>' + content + '</p>').insertAfter($('#img', alertEle));
        // $('#content', alertEle).html(content);
        switch (icontype) {
            case 'success':
                $('#img', alertEle).removeClass().addClass('tipTrue');
                break;
            case 'error':
                $('#img', alertEle).removeClass().addClass('tipFalse');
                break;
            case 'alert':
                $('#img', alertEle).removeClass().addClass('tipAlert');
                break;
            case 'infomation':
                $('#img', alertEle).removeClass().addClass('tipInfo');
                break;
            default:
                $('#img', alertEle).removeClass().addClass('tipInfo');
        }
        if ($.isFunction(callback)) {
            alertEle.dialog({
                title: '【' + title + '】',
                autoOpen: false,
                width: 400,
                modal: true,
                buttons: {
                    "取消": function () {
                        $(this).dialog("close");
                        if (cancelcallback)
                            cancelcallback();
                    },
                    "确定": function () {
                        $(this).dialog("close");
                        callback();
                    }
                }
            });
        } else {
            alertEle.dialog({
                title: '【' + title + '】',
                autoOpen: false,
                width: 400,
                modal: true,

                buttons: {
                    "关闭": function () {
                        $(this).dialog("close");
                    }
                }
            });
        }
        alertEle.dialog('option', 'title', '【' + title + '】').dialog('open');
    };

    $.fn.overlay = function () {
        // var opts = $.extend({}, $.fn.pager.defaults, options);
        var el = this;
        el.options = {};
        el.$el = $.ui.dialog.overlay.create(el);
        // el.$el = new $.ui.dialog.overlay(el);
        el.destoryoverlay = function () {
            $.ui.dialog.overlay.destroy(el.$el);
        };
        return el;
    };

    // 等待状态
    $.waiting = {
        show: function (msg) {
            if (!msg) {
                msg = "正在加载中，请稍后......";
            }
            if (!window.message)
                window.message = {};
            if (!window.message.waiting) {
                window.message.waiting = $(
						'<div class="wait" style="position: absolute;z-index:9999"><img src="/img/waiting.gif" /><span>'
								+ msg + '</span></div>')
						.appendTo(document.body);
            }
            window.message.waiting.overlay().offset({
                top: 0,
                left: 0
            }).css('display', '').position({
                of: window,
                my: 'center center',
                at: 'center center',
                offset: '',
                using: function (pos) {
                    var topOffset = $(this).css(pos).offset().top;
                    if (topOffset < 0) {
                        $(this).css('top', pos.top - topOffset);
                    }
                },
                collision: 'fit'
            }).show();
        },
        hide: function () {
            window.message.waiting.hide().destoryoverlay();
        }
    };
    $.fn.waiting = function (msg) {
        if (!msg) {
            msg = "正在加载中，请稍后......";
        }
        return $(this).empty().append('<img src="" /><span>' + msg + '</span>');
    };

    var initTableLayout = function () {

        var self = $('div.topOperRegion:not(:has(a))')
				.next('div.datacontainer');
        $('table.datalist:first', self).attr('style', 'border-top:0');
        $('div.topOperRegion:not(:has(a))').hide();
    }

    var stripe = $.stripe = function () {
        $('.datalist>tbody>tr:even').children('td').addClass('alt');
        initTableLayout();
        // datalist数据表格鼠标悬停变色
        $(document).on('mouseover', '.datalist>tbody>tr>td', function () {
            $(this).parent('tr').children('td').addClass('over');
        }).on('mouseout', '.datalist>tbody>tr>td', function () {
            $(this).parent('tr').children('td').removeClass('over');
        });
        // $('div.TableRegion').removeShadow().dropShadow({ blur: 1, swap:
        // false, opacity: .5, color: "#999" });

        $('.datalist thead td[sort]').mousedown(function () {
            $(this).addClass('active');
        }).mouseup(function () {
            $(this).removeClass('active');
        });

        // 按钮title提示
        $('a.Edit').attr('title', "编辑");
        $('a.Add').attr('title', "新增");
        $('a.Del').attr('title', "删除");
        $('a.Disabled').attr('title', '禁用');
        $('a.Enabled').attr('title', '启用');
        $('a.ImageAudit').attr('title', '审核');
        $('a.Password').attr('title', '修改密码');
        $('a.ImageReSend').attr('title', '重发');
        $('a.Meet').attr('title', '会见');
        $('a.View').attr('title', '查看');
        $('a.ImageSearch').attr('title', '查询');
        $('a.Reply').attr('title', '回复');
    };
    $.tip = function () {
        $('*[tip]').each(function () {
            var str = $.trim($(this).text());
            var len = parseInt($(this).attr("tip"));
            $(this).attr("title", str).removeAttr("tip");
            if (str.length > len) {
                $(this).text(str.substr(0, len) + "...");
            }
        });
    };
    var initInput = function () {
        var vdt = $(':input[required],select[required]').parent('td')
				.prev('td');
        $('label', vdt).before('<span class="required">*</span>');

        $(
				':input[required],:input[datatype],textarea[maxlength], :input[date],input[tag^="date"]')
				.focus(function () {
				    $(this).InputTip();
				}).blur(function () {
				    $(this).validateele();
				});

        $(':input[maxlength]').keypress(function () {
            var self = $(this);
            var len = self.attr('maxlength');
            if (len) {
                var str = self.val();
                if (str.length > len) {
                    self.validatemsg("最多允许输入" + len + "个字符");
                    return false;
                } else {
                    self.validatemsg("", true);
                }

            }
        });

    };

    $.fn.validatemsg = function (str, success) {

        var ele = this.parent();
        ele.find('span.ErrorTip,span.InputTip').remove();
        if (success) {
            // ele.append($(' <span class="noteCheck true"></span>'));
            return false;
        } else {
            if (this.attr('alert')) {
                $.ActionResponse('error', '提示', this.attr('alert'));
            } else
                this.after('<span class="ErrorTip" style="color:red">' + str
						+ '</span>');
        }
        return true;

    };
    $.fn.resetvalidate = function () {
        this.find('span.ErrorTip').remove();
        return this;
    };
    $.fn.removevalidatemsg = function () {
        var ele = this.parent();
        ele.find('span.ErrorTip').remove();
    };
    $.validate = {};
    $.validate.regexEnum = {
        intege: "^-?[0-9]\\d*$", // 整数
        intege1: "^[1-9]\\d*$", // 正整数
        intege2: "^-[1-9]\\d*$", // 负整数
        num: "^([+-]?)\\d*\\.?\\d+$", // 数字
        num1: "^[1-9]\\d*|0$", // 正数（正整数 + 0）
        num2: "^-[1-9]\\d*|0$", // 负数（负整数 + 0）
        decmal: "^([+-]?)\\d*\\.\\d+$", // 浮点数
        decmal1: "^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$", // 正浮点数
        decmal2: "^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$", // 负浮点数
        decmal3: "^-?([1-9]\\d*.\\d*|0.\\d*[1-9]\\d*|0?.0+|0)$", // 浮点数
        decmal4: "^\d+(\.\d+)?$", // 非负浮点数（正浮点数 + 0）
        decmal5: "^((-\d+(\.\d+)?)|(0+(\.0+)?))$", // 非正浮点数（负浮点数 + 0）

        email: "^\\w+((-\\w+)|(\\.\\w+))*\\@[A-Za-z0-9]+((\\.|-)[A-Za-z0-9]+)*\\.[A-Za-z0-9]+$", // 邮件
        color: "^[a-fA-F0-9]{6}$", // 颜色
        url: "^http[s]?:\\/\\/([\\w-]+\\.)+[\\w-]+([\\w-./?%&=]*)?$", // url
        chinese: "^[\\u4E00-\\u9FA5\\uF900-\\uFA2D]+$", // 仅中文
        ascii: "^[\\x00-\\xFF]+$", // 仅ACSII字符
        zipcode: "^\\d{6}$", // 邮编
        mobile: "^(13|14|15|18)[0-9]{9}$", // 手机
        ip4: "^(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)$", // ip地址
        notempty: "^\\S+$", // 非空
        picture: "(.*)\\.(jpg|bmp|gif|ico|pcx|jpeg|tif|png|raw|tga)$", // 图片
        rar: "(.*)\\.(rar|zip|7zip|tgz)$", // 压缩文件
        xls: "(.*)\\.(xls|xlsx)$",
        date: "^\\d{4}(\\-|\\/|\.)\\d{1,2}\\1\\d{1,2}$", // 日期
        qq: "^[1-9]*[1-9][0-9]*$", // QQ号码
        tel: "^(([0\\+]\\d{2,3}-)?(0\\d{2,3})-)?(\\d{7,8})(-(\\d{3,}))?$", // 电话号码的函数(包括验证国内区号,国际区号,分机号)
        username: "^\\w+$", // 用来用户注册。匹配由数字、26个英文字母或者下划线组成的字符串
        letter: "^[A-Za-z]+$", // 字母
        letter_u: "^[A-Z]+$", // 大写字母
        letter_l: "^[a-z]+$", // 小写字母
        idcard: "^[1-9]([0-9]{14}|[0-9]{17})$", // 身份证
        filepath: "^[a-z]:(//||\\\\)[\\w\\u4e00-\\u9fa5\\s]+((([/\\\\][\\w\\u4e00-\\u9fa5\\s]+)*$)||$)" // 文件路径
    };
    $.validate.regexEnumMsg = {
        all: "请输入",
        intege: "输入大于等于0的整数", // 整数
        intege1: "输入大于0的整数", // 正整数
        intege2: "输入小于0的整数", // 负整数
        num: "输入整数或带小数点的数字", // 数字
        num1: "输入正数", // 正数（正整数 + 0）
        num2: "输入负数", // 负数（负整数 + 0）
        decmal: "输入带小数点的数字", // 浮点数
        decmal1: "输入带小数点的正数", // 正浮点数
        decmal2: "输入带小数点的负数", // 负浮点数
        decmal3: "输入带小数点的数字", // 浮点数
        decmal4: "非负浮点数", // 非负浮点数（正浮点数 + 0）
        decmal5: "^((-\d+(\.\d+)?)|(0+(\.0+)?))$", // 非正浮点数（负浮点数 + 0）

        email: "^输入邮箱", // 邮件
        color: "^[a-fA-F0-9]{6}$", // 颜色
        url: "^http[s]?:\\/\\/([\\w-]+\\.)+[\\w-]+([\\w-./?%&=]*)?$", // url
        chinese: "^[\\u4E00-\\u9FA5\\uF900-\\uFA2D]+$", // 仅中文
        ascii: "^[\\x00-\\xFF]+$", // 仅ACSII字符
        zipcode: "^\\d{6}$", // 邮编
        mobile: "输入手机号", // 手机
        ip4: "^(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)$", // ip地址
        notempty: "^\\S+$", // 非空
        picture: "(.*)\\.(jpg|bmp|gif|ico|pcx|jpeg|tif|png|raw|tga)$", // 图片
        rar: "(.*)\\.(rar|zip|7zip|tgz)$", // 压缩文件
        xls: "xls文件",
        date: "^\\d{4}(\\-|\\/|\.)\\d{1,2}\\1\\d{1,2}$", // 日期
        qq: "输入QQ号", // QQ号码
        tel: "[区号-]号码[-分机号]", // 如：[0531-]8888888[-123]，[]里的内容可选//电话号码的函数(包括验证国内区号,国际区号,分机号)
        username: "^\\w+$", // 用来用户注册。匹配由数字、26个英文字母或者下划线组成的字符串
        letter: "^[A-Za-z]+$", // 字母
        letter_u: "^[A-Z]+$", // 大写字母
        letter_l: "^[a-z]+$", // 小写字母
        idcard: "输入身份证号", // 身份证
        filepath: "请输入文件路径,如D:\\SDCM\\BackUp" // 文件路径
    };
    $.fn.InputTip = function (message) {
        var self = $(this);
        self.nextAll('span.ErrorTip,span.InputTip').remove();

        var datatype = self.attr('datatype') || self.attr('required');
        if (datatype == '*')
            datatype = 'all';

        var msg = message || self.attr('inputtip')
				|| $.validate.regexEnumMsg[datatype] || "";
        // span.InputTip

        // var reqEle = self.attr('required') ? self.next('span.required') :
        // self;
        self.after('<span class="InputTip">' + msg + '</span>');
    };
    initInput();
    // $(':input[required]').parent().prev('dt').after('<span
    // class="required">*</span>');

    $.fn.validateele = function () {
        var self = $(this);
        // 移除输入提示
        $(this).validatemsg('a', true);

        var elename = self.attr['elename']
				|| $(self.parent('td').prev('td')).text().replace(':', '')
						.replace('：', '').replace(' ', '');

        // 检测元素有没有绑定onvalidate事件，如果绑定了则使用元素自定义的验证方案
        var event = jQuery.Event("onvalidate");
        self.trigger(event);
        if (event.result) {
            if (event.result.success)
                return true;
            else {
                self.validatemsg(event.result.msg);
                return false;
            }
        }

        // 是否跳过隐藏域的验证
        if (self.is(':hidden') && self.attr('skip') != "no")
            return true;
        var isRequired = self.attr('required');
        var datatype = self.attr('datatype');

        // 检测时间范围
        if (self.attr("tag") == "datetime" || self.attr("tag") == "datetime") {
            if (self.val() != '') {
                var option = self.getContraryDate();
                var t = option.targetInput;
                if (t.length > 0) {
                    if (t.val() != '') {
                        var date = self.datepicker("getDate");
                        var targetdate = t.datepicker("getDate");
                        if (date < targetdate != option.isMin) {
                            if (option.isMin) {
                                t.validatemsg("日期范围错误");
                            } else {
                                self.validatemsg("日期范围错误");
                            }
                            return false;
                        }

                    }
                }
            }
        }

        // 检测是否超出长度
        if (self.is("textarea")) {
            var len = self.attr('maxlength');
            if (len) {
                var str = self.val();
                if (str.length > len) {
                    self.validatemsg("最多允许输入" + len + "个字符");
                    return false;
                }
            }

        }

        if (!isRequired && !datatype)
            return true;
        if (!isRequired && self.val() == '')
            return true;

        if (isRequired && isRequired != '*') {
            datatype = datatype || isRequired;
        }
        var vMsg = self.attr['inputmsg'];
        if (isRequired
				&& self.is(":text,:file,input:hidden,textarea,:password")
				&& self.val() == '') {
            if (self.is(":file")) {
                self.validatemsg(vMsg || '请选择文件！');
            } else {
                self.validatemsg(vMsg || '请输入' + elename);
            }
            return false;
        } else if (self.is(':radio')) {
            var eles = $.radio(self.attr("name"));
            if (!eles.val()) {
                eles.last().validatemsg(vMsg || '请选择' + elename);
                return false;
            } else {
                return true;
            }

        } else if (self.is('select')) {
            if (self.val() == '') {
                self.validatemsg(vMsg || '请选择' + elename);
                return false;
            }
            return true;
        } else {
            if (!datatype || datatype == '*')
                return true;
            var regexpress = eval("$.validate.regexEnum." + datatype);
            if ((new RegExp(regexpress, "i")).test(self.val())) {
                return true;
            }
            self.validatemsg(elename + '输入格式不正确');
            return false;
        }
    };
    $.fn.validate = function () {
        if (this.length == 1 && this.is('form')) {
            return this.find(':input').validate();
        }
        var ret = true;
        this.each(function () {
            if (!$(this).validateele()) {
                ret = false;
                return ret;
            } else {
                if ($(this).attr('required'))
                    $(this).validatemsg('a', true);
                else
                    $(this).removevalidatemsg();

            }
        });
        return ret;

    };

    // 绑定autocomplete //TODO:to be continue
    $.autocomplete = {
        split: function (val) {
            return val.split(/[,，]\s*/);
        },
        extractLast: function (term) {
            return $.autocomplete.split(term).pop();
        },
        // 去除无效数据
        validate: function (ele) {
            var valfield = ele.attr('valuefield');
            var disfield = ele.attr('displayfield') || valfield;
            var terms = $.autocomplete.split(ele.val());
            // 检查数据的有效性
            var data = ele.data('selectdata') || [];

            // 去掉terms里没有的数据
            data = $.grep(data, function (n, i) {
                for (var j in terms) {
                    if (terms[j] == $.getDataByTemplate(n, disfield)) {
                        return true;
                    }
                }
                return false;
            });
            // 去掉无效term
            terms = $.grep(terms, function (n, i) {
                for (var i in data) {
                    if (n == $.getDataByTemplate(data[i], disfield)) {
                        return true;
                    }
                }
                return false;
            });

            ele.data('selectdata', data);
            // //转换为提交数据
            // ele.toSubmitData(data);
            return terms;
        },

        init: function () {
            var eles = $(":text.autocomplete")
					.autocomplete(
							{
							    source: function (request, response) {
							        // var self = this;
							        var ele = this.element;

							        var term = ele.attr('searchfield')
											|| ele.attr('displayfield')
											|| 'term';
							        var oQuery = {
							            PageIndex: 1,
							            PageSize: ele.attr('pagesize') || 5
							        };
							        oQuery[term] = $.autocomplete
											.extractLast(request.term);
							        $.getJSON(ele.attr('href'), oQuery,
											function (data) {
											    response(data.Data || data);
											});
							    },
							    search: function () {
							        // custom minLength
							        var term = $.autocomplete
											.extractLast(this.value);
							        // 检测是否和上次输入的一样
							        var oldterm = this._previnput;
							        if ($.trim(this.value) == oldterm) {
							            return false;
							        }
							        this._previnput = this.value;

							        if (term.length < 2) {
							            return false;
							        }
							    },
							    focus: function () {
							        // prevent value inserted on focus
							        return false;
							    },
							    select: function (event, ui) {
							        var ele = $(this);

							        var valfield = ele.attr('valuefield');
							        var disfield = ele.attr('displayfield')
											|| valfield;
							        var terms = $.autocomplete
											.split(this.value);
							        // remove the current input
							        terms.pop();
							        terms = $.autocomplete.validate(ele);
							        var data = ele.data('selectdata') || [];
							        var isCanAdd = true;
							        for (var i in data) {
							            // 如果已经存在则返回
							            if (ui.item[valfield] == data[i][valfield]) {
							                isCanAdd = false;
							                break;
							            }
							        }
							        if (isCanAdd) {
							            // add the selected item
							            terms.push($.getDataByTemplate(ui.item,
												disfield));
							            data.push(ui.item);
							        }
							        // add placeholder to get the
							        // comma-and-space at the end
							        terms.push("");
							        this.value = terms.join(",");
							        ele.attr('title', this.value);
							        ele.data('selectdata', data);

							        // 转换为提交数据
							        // ele.toSubmitData(data);

							        // if ($.TraceEnabled) {
							        // $.Trace('----------------------');
							        // for (var i in data) {
							        // $.Trace($.getDataByTemplate(data[i],
							        // disfield));
							        // }
							        // }

							        return false;
							    }
							});
            if (eles.length > 0) {
                eles.blur(function () {
                    var ele = $(this);
                    var terms = $.autocomplete.validate(ele);
                    terms.push("");
                    this.value = terms.join(",");
                    ele.attr('title', this.value);
                    var data = ele.data('selectdata');
                    ele.toSubmitData(data);
                    $(this).InputTip('已将无效内容移除');
                });
                eles.data("autocomplete")._renderItem = function (ul, item) {
                    var ele = this.element;
                    var template = $('#' + ele.attr("id") + "Template").html()
							|| "<a>{{"
							+ (ele.attr('displayfield') || ele
									.attr('valuefield')) + "}}</a>";
                    return $("<li></li>").data("item.autocomplete", item)
							.append($.getDataByTemplate(item, template))
							.appendTo(ul);
                };
            }

        }
    };
    $.autocomplete.init();

    // 清空数据
    $.fn.resetInput = function () {
        var eles = $(":input", this);
        if (eles.length == 0)
            eles = this;
        return eles.each(function () {

            var self = $(this);
            if (self.is(":checkbox") || self.is(':radio'))
                return;
            if (this.name == "Id")
                self.val(0);
            else
                self.val(self.attr('defaultval') || "");
        });

    };

    $.fn.bindSelectOption = function (href, json, tag) {
        this.empty();
        if ($("#" + tag).attr("defaultoption") != "false") {
            $("#" + tag).append(
					"<option value=" + "" + ">" + "请选择" + "</option>");
        }
        $.post(href, json, function (data) {
            for (var i = 0; i < data.length; i++) {
                $("#" + tag).append(
						"<option value=" + data[i].value + ">" + data[i].text
								+ "</option>");
            }
        }, 'json');
    };

    // 绑定dialog数据
    $.fn.bindDlgData = function (href, callback, defaultFieldNameSpace) {
        // $.waiting.show();
        this.resetInput();
        var ele = this;
        ele.resetvalidate();
        $('.edithide', ele).hide();
        $.post(href, {}, function (data) {
            $(':input[name],*[datafield]', ele).binddata(data.data,
					defaultFieldNameSpace);
            // $.waiting.hide();
            ele.dialog('open');
            if ($.isFunction(callback)) {
                callback(data);
            }
        }, 'json');

    };

    $.fn.bindDlgHtml = function (href, callback) {
        $.waiting.show();
        var ele = this;
        ele.resetvalidate();
        $('div.content', ele).load(href, function () {
            initInput();
            $.waiting.hide();
            ele.dialog('open');
            if ($.isFunction(callback))
                callback();
        });
    };

    // TODO:修改form.submit监听方法，将 $(ele).data('submitdata')变成 <input type="hidden"
    // name="[datafield][0].[valuefield]" value="1" />
    // 传入一个对象数组，并且当前元素上有displayfield,valuefield属性,并将Value绑定到this.data('submitdata')={"[datafield][0].[valuefield]"=value1,"[datafield][1].[valuefield]"=value1}里
    $.fn.bindArray = function (data) {
        var displayfield = this.attr('displayfield');
        var strDisplay = "";
        if (displayfield) {
            for (var i = 0; i < data.length; i++) {
                var item = data[i];
                strDisplay += $.getDataByTemplate(item, displayfield) + ",";
            }
        }
        this.val(strDisplay);
        this.toSubmitData(data);
    };
    // 将数据转换为提交数据
    $.fn.toSubmitData = function (data) {
        var valuefield = this.attr('valuefield');
        var datafield = this.attr('datafield');
        if (!valuefield)
            return false;
        this.data('selectdata', data);
        var prefix = this.attr('id') + "_data";
        $('input:hidden.' + prefix).remove();

        for (var i = 0; i < data.length; i++) {
            var item = data[i];
            var obj = {};
            obj.name = datafield + '.' + valuefield; // +'[' + i.toString() +
            // '].' + valuefield;
            obj.value = $.getDataByTemplate(item, valuefield);
            this.after($('<input type="hidden" />').attr(obj).addClass(prefix));
        }
        // if ($.TraceEnabled) {
        // $.Trace('----------------------');
        // $('input:hidden.' + prefix).each(function() {
        // $.Trace($(this).attr('name') + ":" + $(this).val());
        // })
        // }

    };

    // 解析数据模板
    $.getDataByTemplate = function (data, template, defaultFieldNameSpace) {
        var getData = function (data, field) {
            if (defaultFieldNameSpace && field.indexOf(".") <= 0) {
                field = defaultFieldNameSpace + "." + field;
            }
            var item = data;
            var arrFields = field.split(".");
            for (var i = 0; i < arrFields.length; i++) {
                item = item[arrFields[i]];
                if (item == null || item == undefined) {
                    break;
                }
            }
            if (item == undefined) {
                item = null;
            }
            return item;
        };
        var item;
        // 替换例如 datafield="部门:{{Department.Name}}"的表达式
        var re = /\{\{([^\}]*)\}\}/g;
        if (re.test(template)) {
            item = template.replace(re, function () {
                return getData(data, arguments[1]) || "";
            });
        } else {
            // 简单的替换 datefield="Department.Name"类型的值
            item = getData(data, template);
        }
        return item;
    };

    // 绑定数据
    $.fn.binddata = function (data, defaultFieldNameSpace) {
        if (!data)
            return false;
        // 绑定数据到页面元素
        // defaultFieldPrefix,如果没有前面的名字则使用默认的名字，如"aa"则成为"name.aa","aa.bb"则不变
        return this
				.each(function () {
				    var self = $(this);
				    var field = $(this).attr("datafield") || this.name;

				    if (field == undefined || field == null || field == "")
				        return;

				    var item = $.getDataByTemplate(data, field,
							defaultFieldNameSpace);

				    if (self.is(':checkbox')) {
				        if (item != null
								&& (item == true || item == "1" || item
										.toString().toLowerCase() == "true")) {
				            self.attr("checked", true);
				        } else {
				            self.removeAttr("checked");
				        }

				    } else if (self.is(':radio')) {
				        if (item != null && this.value == item.toString()) {
				            self.attr("checked", true);
				        }
				    } else if (self.is('select')) {
				        var subitem = self.children('option[value="' + item
								+ '"]');
				        if (subitem.length == 0) {
				            self.attr('selval', item);
				        } else {
				            self.removeAttr('selval').val(item);
				        }
				    } else {
				        if (item != null) {
				            // 处理日期数据
				            if (item.getDate) {
				                var str = item.format(self.attr('format')
										|| 'isoDate');
				                if (self.is(':input'))
				                    self.val(str);
				                else
				                    self.text(str);
				            } else {
				                if (self.is(':input')) {
				                    // 如果是数组并且定义了数组显示规则
				                    if ($.isArray(item)
											&& self.attr('displayfield'))
				                        self.bindArray(item);
				                    else
				                        self.val(item);
				                } else {
				                    self.text(item);
				                }
				            }

				        } else {
				            self.val('');
				        }
				    }
				    self.change();

				});
    };

    stripe();
});

(function () {
    function jRadio(name) {
        this.elements = $('input[type=radio][name=' + name + ']');
        this.lastVal = jRadio.prototype.val.apply(this);
    }
    jRadio.prototype.last = function () {
        return $(this.elements[this.elements.length - 1]);
    };
    jRadio.prototype.change = function (callback) {
        var self = this;
        this.elements.click(function () {
            var val = self.val();
            if (val != self.lastVal) {
                self.lastVal = val;
                callback(self);
            }
        })
    }
    jRadio.prototype.val = function (val) {
        if (val === undefined) {
            return this.elements.filter(function () {
                return this.checked;
            }).val();
        } else {
            if (this.lastVal == val)
                return;
            this.lastVal = val;
            this.elements.filter(function () {
                return $(this).val() == val;
            }).attr('checked', true);
            return this;
        }
    }

    $.radio = function (name) {
        return new jRadio(name);
    }
})();

String.prototype.isEmail = function () {
    var reg = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1,2})$/;
    return reg.test(this);
}
String.prototype.len = function () {
    return this.replace(/[^\x00-\xff]/g, "**").length;
}

/*
* jqURL by Josh Nathanson
* 
* various manipulations on url strings and windows. all functions can also take
* a window object as an argument, for example {win:opener} but will default to
* current window if none is passed.
* 
* public functions:
* 
* ------------------------- .url({ win:window object })
* ------------------------- returns the whole url string like win.location.href
* 
* so if the current window href is "http://www.mysite.com?var1=1&var2=2&var3=3"
* 
* $.jqURL.url() returns "http://www.mysite.com?var1=1&var2=2&var3=3"
* 
* 
* ------------------------------ .loc(urlstr:string, { win:window object,
* w:integer, h:integer, t:integer, l:integer,
* wintype:string('_top'[default],'_blank','_parent') ) })
* ------------------------------ - directs passed in window to urlstr, which is
* required - works like window.location.href = 'myurl' - but you can also use
* it to pop open a new window by passing in "_blank" as the wintype - if
* popping open a window, defaults to center of screen
* 
* so $.jqURL.loc('http://www.google.com', {w:200,h:200,wintype:'_blank'});
* would open Google in a new centered 200x200 window
* 
* or, locate an url to any named window: $.jqURL.loc('http://www.google.com',{
* win:mywindow }); opens Google in mywindow
* 
* 
* ------------------------------ .qs({ ret:string('string'[default],'object'),
* win:window object }) ------------------------------ returns querystring,
* either string (pass ret:'string' [default]) or object (pass ret:'object')
* 
* so if the current window href is "http://www.mysite.com?var1=1&var2=2&var3=3"
* 
* $.jqURL.qs(); returns "var1=1&var2=2&var3=3"
* 
* $.jqURL.qs({ ret:'object' }); returns Object var1=1,var2=2,var3=3
* 
* 
* ------------------------------ .strip({ keys:string(list of keys to strip),
* win:window object }) ------------------------------ if passed with no
* arguments, returns url with '?' and query string removed if you pass in list
* of keys, it returns url with the specified key-value pairs removed
* 
* so if the current window href is "http://www.mysite.com?var1=1&var2=2&var3=3"
* 
* $.jqURL.strip(); will return "http://www.mysite.com"
* 
* $.jqURL.strip({ keys:'var1,var2' }); will return
* "http://www.mysite.com?var3=3"
* 
* 
* ------------------------------------- .get(key, {win:window object})
* ------------------------------------- returns value of passed in querystring
* key
* 
* so if the current window href is "http://www.mysite.com?var1=1&var2=2&var3=3"
* $.jqURL.get('var2'); will return 2
* 
* -------------------------------------- .set(hash, {win:window object})
* -------------------------------------- returns the window's url, but with the
* keys/values set in the query string if the keys already exist, re-sets the
* value if they don't exist, they're appended onto the query string
* 
*/

jQuery.jqURL = {

    url: // returns a string
	function (args) {
	    args = jQuery.extend({
	        win: window
	    }, args);
	    return args.win.location.href;
	},

    loc: function (urlstr, args) {
        args = jQuery.extend({
            win: window,
            w: 500,
            h: 500,
            wintype: '_top'
        }, args);

        if (!args.t) {
            args.t = screen.height / 2 - args.h / 2;
        }
        if (!args.l) {
            args.l = screen.width / 2 - args.w / 2;
        }
        if (args['wintype'] == '_top') {
            args.win.location.href = urlstr;
        } else {
            open(urlstr, args['wintype'], 'width=' + args.w + ',height='
					+ args.h + ',top=' + args.t + ',left=' + args.l
					+ ',scrollbars,resizable');

        }
        return;
    },

    qs: function (args) {
        args = jQuery.extend({
            ret: 'string',
            win: window
        }, args);

        if (args['ret'] == 'string') {
            return jQuery.jqURL.url({
                win: args.win
            }).split('?')[1];
        }

        else if (args['ret'] == 'object') {

            var qsobj = {};
            var thisqs = jQuery.jqURL.url({
                win: args.win
            }).split('?')[1];

            if (thisqs) {
                var pairs = thisqs.split('&');
                for (i = 0; i < pairs.length; i++) {
                    var pair = pairs[i].split('=');
                    qsobj[pair[0]] = pair[1];
                }
            }
            return qsobj;
        }
    },

    strip: function (args) {
        args = jQuery.extend({
            keys: '',
            win: window
        }, args);

        if (jQuery.jqURL.url().indexOf('?') == -1) { // no query string found
            return jQuery.jqURL.url({
                win: args.win
            });
        }
        // if no keys passed in, just return url with no querystring
        else if (!args.keys) {
            return jQuery.jqURL.url({
                win: args.win
            }).split('?')[0];
        } else { // return stripped url

            var qsobj = jQuery.jqURL.qs({
                ret: 'object',
                win: args.win
            }); // object with key/value pairs
            var counter = 0;
            var url = jQuery.jqURL.url({
                win: args.win
            }).split('?')[0] + '?';
            var amp = '';

            for (var key in qsobj) {
                if (args.keys.indexOf(key) == -1) {
                    // pass test, add this key/value to string
                    amp = (counter) ? '&' : '';
                    url = url + amp + key + '=' + qsobj[key];
                    counter++;
                }
            }
            return url;
        }
    },

    get: function (key, args) {
        args = jQuery.extend({
            win: window
        }, args);

        qsobj = jQuery.jqURL.qs({
            ret: 'object',
            win: args.win
        });
        return qsobj[key];
    },

    set: function (hash, args) {
        args = jQuery.extend({
            win: window
        }, args);

        // get current querystring
        var qsobj = jQuery.jqURL.qs({
            ret: 'object',
            win: args.win
        });

        // add/set values from hash
        for (var i in hash) {
            qsobj[i] = hash[i];
        }

        var qstring = '';
        var counter = 0;
        var amp = '';

        // turn qsobj into string
        for (var k in qsobj) {
            amp = (counter) ? '&' : '';
            qstring = qstring + amp + k + '=' + qsobj[k];
            counter++;
        }
        return jQuery.jqURL.strip({
            win: args.win
        }) + '?' + qstring;
    }

};

/*
* Date Format 1.2.3 (c) 2007-2009 Steven Levithan <stevenlevithan.com> MIT
* license
* 
* Includes enhancements by Scott Trenda <scott.trenda.net> and Kris Kowal
* <cixar.com/~kris.kowal/>
* 
* Accepts a date, a mask, or a date and a mask. Returns a formatted version of
* the given date. The date defaults to the current date/time. The mask defaults
* to dateFormat.masks.default.
*/

var dateFormat = function () {
    var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, timezoneClip = /[^-+\dA-Z]/g, pad = function (
			val, len) {
        val = String(val);
        len = len || 2;
        while (val.length < len)
            val = "0" + val;
        return val;
    };

    // Regexes and supporting functions are cached through closure
    return function (date, mask, utc) {
        var dF = dateFormat;

        // You can't provide utc if you skip other args (use the "UTC:" mask
        // prefix)
        if (arguments.length == 1
				&& Object.prototype.toString.call(date) == "[object String]"
				&& !/\d/.test(date)) {
            mask = date;
            date = undefined;
        }

        // Passing date through Date applies Date.parse, if necessary
        date = date ? new Date(date) : new Date;
        if (isNaN(date))
            throw SyntaxError("invalid date");

        mask = String(dF.masks[mask] || mask || dF.masks["default"]);

        // Allow setting the utc argument via the mask
        if (mask.slice(0, 4) == "UTC:") {
            mask = mask.slice(4);
            utc = true;
        }

        var _ = utc ? "getUTC" : "get", d = date[_ + "Date"](), D = date[_
				+ "Day"](), m = date[_ + "Month"](), y = date[_ + "FullYear"](), H = date[_
				+ "Hours"](), M = date[_ + "Minutes"](), s = date[_ + "Seconds"]
				(), L = date[_ + "Milliseconds"](), o = utc ? 0 : date
				.getTimezoneOffset(), flags = {
				    d: d,
				    dd: pad(d),
				    ddd: dF.i18n.dayNames[D],
				    dddd: dF.i18n.dayNames[D + 7],
				    m: m + 1,
				    mm: pad(m + 1),
				    mmm: dF.i18n.monthNames[m],
				    mmmm: dF.i18n.monthNames[m + 12],
				    yy: String(y).slice(2),
				    yyyy: y,
				    h: H % 12 || 12,
				    hh: pad(H % 12 || 12),
				    H: H,
				    HH: pad(H),
				    M: M,
				    MM: pad(M),
				    s: s,
				    ss: pad(s),
				    l: pad(L, 3),
				    L: pad(L > 99 ? Math.round(L / 10) : L),
				    t: H < 12 ? "a" : "p",
				    tt: H < 12 ? "am" : "pm",
				    T: H < 12 ? "A" : "P",
				    TT: H < 12 ? "AM" : "PM",
				    Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop()
					.replace(timezoneClip, ""),
				    o: (o > 0 ? "-" : "+")
					+ pad(
							Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o)
									% 60, 4),
				    S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0
					: (d % 100 - d % 10 != 10) * d % 10]
				};

        return mask.replace(token, function ($0) {
            return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
        });
    };
} ();

// Some common format strings
dateFormat.masks = {
    "default": "ddd mmm dd yyyy HH:MM:ss",
    shortDate: "m/d/yy",
    mediumDate: "mmm d, yyyy",
    longDate: "mmmm d, yyyy",
    fullDate: "dddd, mmmm d, yyyy",
    shortTime: "h:MM TT",
    mediumTime: "h:MM:ss TT",
    longTime: "h:MM:ss TT Z",
    isoDate: "yyyy-mm-dd",
    isoTime: "HH:MM:ss",
    minute: "yyyy-mm-dd HH:MM",
    isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
    isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
};

// Internationalization strings
dateFormat.i18n = {
    dayNames: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday",
			"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
    monthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
			"Sep", "Oct", "Nov", "Dec", "January", "February", "March",
			"April", "May", "June", "July", "August", "September", "October",
			"November", "December"]
};

// For convenience...
Date.prototype.format = function (mask, utc) {
    return dateFormat(this, mask, utc);
};

Date.MillisecondToDate = function (msd) {
    var time = parseFloat(msd) / 1000;
    if (null != time && "" != time) {
        if (time > 60 && time < 60 * 60) {
            time = parseInt(time / 60.0)
					+ "分钟"
					+ parseInt((parseFloat(time / 60.0) - parseInt(time / 60.0)) * 60)
					+ "秒";
        } else if (time >= 60 * 60 && time < 60 * 60 * 24) {
            time = parseInt(time / 3600.0)
					+ "小时"
					+ parseInt((parseFloat(time / 3600.0) - parseInt(time / 3600.0)) * 60)
					+ "分钟"
					+ parseInt((parseFloat((parseFloat(time / 3600.0) - parseInt(time / 3600.0)) * 60) - parseInt((parseFloat(time / 3600.0) - parseInt(time / 3600.0)) * 60)) * 60)
					+ "秒";
        } else {
            time = parseInt(time) + "秒";
        }
    }
    return time;
};

if (!this.JSON) {

    // Create a JSON object only if one does not already exist. We create the
    // object in a closure to avoid global variables.

    JSON = function () {

        function f(n) { // Format integers to have at least two digits.
            return n < 10 ? '0' + n : n;
        }

        Date.prototype.toJSON = function () {

            // Eventually, this method will be based on the date.toISOString
            // method.

            return this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1)
					+ '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours())
					+ ':' + f(this.getUTCMinutes()) + ':'
					+ f(this.getUTCSeconds()) + 'Z';
        };

        var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g, gap, indent, meta = { // table
            // of
            // character
            // substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"': '\\"',
            '\\': '\\\\'
        }, rep;

        function quote(string) {

            // If the string contains no control characters, no quote
            // characters, and no
            // backslash characters, then we can safely slap some quotes around
            // it.
            // Otherwise we must also replace the offending characters with safe
            // escape
            // sequences.

            return escapeable.test(string) ? '"'
					+ string.replace(escapeable, function (a) {
					    var c = meta[a];
					    if (typeof c === 'string') {
					        return c;
					    }
					    c = a.charCodeAt();
					    return '\\u00' + Math.floor(c / 16).toString(16)
								+ (c % 16).toString(16);
					}) + '"' : '"' + string + '"';
        }

        function str(key, holder) {

            // Produce a string from holder[key].

            var i, // The loop counter.
			k, // The member key.
			v, // The member value.
			length, mind = gap, partial, value = holder[key];

            // If the value has a toJSON method, call it to obtain a replacement
            // value.

            if (value && typeof value === 'object'
					&& typeof value.toJSON === 'function') {
                value = value.toJSON(key);
            }

            // If we were called with a replacer function, then call the
            // replacer to
            // obtain a replacement value.

            if (typeof rep === 'function') {
                value = rep.call(holder, key, value);
            }

            // What happens next depends on the value's type.

            switch (typeof value) {
                case 'string':
                    return quote(value);

                case 'number':

                    // JSON numbers must be finite. Encode non-finite numbers as
                    // null.

                    return isFinite(value) ? String(value) : 'null';

                case 'boolean':
                case 'null':

                    // If the value is a boolean or null, convert it to a string.
                    // Note:
                    // typeof null does not produce 'null'. The case is included
                    // here in
                    // the remote chance that this gets fixed someday.

                    return String(value);

                    // If the type is 'object', we might be dealing with an object
                    // or an array or
                    // null.

                case 'object':

                    // Due to a specification blunder in ECMAScript, typeof null is
                    // 'object',
                    // so watch out for that case.

                    if (!value) {
                        return 'null';
                    }

                    // Make an array to hold the partial results of stringifying
                    // this object value.

                    gap += indent;
                    partial = [];

                    // If the object has a dontEnum length property, we'll treat it
                    // as an array.

                    if (typeof value.length === 'number'
						&& !(value.propertyIsEnumerable('length'))) {

                        // The object is an array. Stringify every element. Use null
                        // as a placeholder
                        // for non-JSON values.

                        length = value.length;
                        for (i = 0; i < length; i += 1) {
                            partial[i] = str(i, value) || 'null';
                        }

                        // Join all of the elements together, separated with commas,
                        // and wrap them in
                        // brackets.

                        v = partial.length === 0 ? '[]' : gap ? '[\n' + gap
							+ partial.join(',\n' + gap) + '\n' + mind + ']'
							: '[' + partial.join(',') + ']';
                        gap = mind;
                        return v;
                    }

                    // If the replacer is an array, use it to select the members to
                    // be stringified.

                    if (typeof rep === 'object') {
                        length = rep.length;
                        for (i = 0; i < length; i += 1) {
                            k = rep[i];
                            if (typeof k === 'string') {
                                v = str(k, value, rep);
                                if (v) {
                                    partial.push(quote(k) + (gap ? ': ' : ':') + v);
                                }
                            }
                        }
                    } else {

                        // Otherwise, iterate through all of the keys in the object.

                        for (k in value) {
                            v = str(k, value, rep);
                            if (v) {
                                partial.push(quote(k) + (gap ? ': ' : ':') + v);
                            }
                        }
                    }

                    // Join all of the member texts together, separated with commas,
                    // and wrap them in braces.

                    v = partial.length === 0 ? '{}' : gap ? '{\n' + gap
						+ partial.join(',\n' + gap) + '\n' + mind + '}' : '{'
						+ partial.join(',') + '}';
                    gap = mind;
                    return v;
            }
        }

        // Return the JSON object containing the stringify, parse, and quote
        // methods.

        return {
            stringify: function (value, replacer, space) {

                // The stringify method takes a value and an optional replacer,
                // and an optional
                // space parameter, and returns a JSON text. The replacer can be
                // a function
                // that can replace values, or an array of strings that will
                // select the keys.
                // A default replacer method can be provided. Use of the space
                // parameter can
                // produce text that is more easily readable.

                var i;
                gap = '';
                indent = '';
                if (space) {

                    // If the space parameter is a number, make an indent string
                    // containing that
                    // many spaces.

                    if (typeof space === 'number') {
                        for (i = 0; i < space; i += 1) {
                            indent += ' ';
                        }

                        // If the space parameter is a string, it will be used
                        // as the indent string.

                    } else if (typeof space === 'string') {
                        indent = space;
                    }
                }

                // If there is no replacer parameter, use the default replacer.

                if (!replacer) {
                    rep = function (key, value) {
                        if (!Object.hasOwnProperty.call(this, key)) {
                            return undefined;
                        }
                        return value;
                    };

                    // The replacer can be a function or an array. Otherwise,
                    // throw an error.

                } else if (typeof replacer === 'function'
						|| (typeof replacer === 'object' && typeof replacer.length === 'number')) {
                    rep = replacer;
                } else {
                    throw new Error('JSON.stringify');
                }

                // Make a fake root object containing our value under the key of
                // ''.
                // Return the result of stringifying the value.

                return str('', {
                    '': value
                });
            },

            parse: function (text, reviver) {

                // The parse method takes a text and an optional reviver
                // function, and returns
                // a JavaScript value if the text is a valid JSON text.

                var j;

                function walk(holder, key) {

                    // The walk method is used to recursively walk the resulting
                    // structure so
                    // that modifications can be made.

                    var k, v, value = holder[key];
                    if (value && typeof value === 'object') {
                        for (k in value) {
                            if (Object.hasOwnProperty.call(value, k)) {
                                v = walk(value, k);
                                if (v !== undefined) {
                                    value[k] = v;
                                } else {
                                    delete value[k];
                                }
                            }
                        }
                    }
                    return reviver.call(holder, key, value);
                }

                // Parsing happens in three stages. In the first stage, we run
                // the text against
                // regular expressions that look for non-JSON patterns. We are
                // especially
                // concerned with '()' and 'new' because they can cause
                // invocation, and '='
                // because it can cause mutation. But just to be safe, we want
                // to reject all
                // unexpected forms.

                // We split the first stage into 4 regexp operations in order to
                // work around
                // crippling inefficiencies in IE's and Safari's regexp engines.
                // First we
                // replace all backslash pairs with '@' (a non-JSON character).
                // Second, we
                // replace all simple value tokens with ']' characters. Third,
                // we delete all
                // open brackets that follow a colon or comma or that begin the
                // text. Finally,
                // we look to see that the remaining characters are only
                // whitespace or ']' or
                // ',' or ':' or '{' or '}'. If that is so, then the text is
                // safe for eval.

                if (/^[\],:{}\s]*$/
						.test(text
								.replace(/\\["\\\/bfnrtu]/g, '@')
								.replace(
										/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
										']')
								.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

                    // In the second stage we use the eval function to compile
                    // the text into a
                    // JavaScript structure. The '{' operator is subject to a
                    // syntactic ambiguity
                    // in JavaScript: it can begin a block or an object literal.
                    // We wrap the text
                    // in parens to eliminate the ambiguity.

                    j = eval('(' + text + ')');

                    // In the optional third stage, we recursively walk the new
                    // structure, passing
                    // each name/value pair to a reviver function for possible
                    // transformation.

                    return typeof reviver === 'function' ? walk({
                        '': j
                    }, '') : j;
                }

                // If the text is not JSON parseable, then a SyntaxError is
                // thrown.

                throw new SyntaxError('JSON.parse');
            },

            quote: quote
        };
    } ();

}
